package com.heima.article.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.heima.article.constants.ArticleConstants;
import com.heima.article.mapper.ApArticleMapper;

import com.heima.article.service.HotArticleService;
import com.heima.common.redis.CacheService;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.vos.HotArticleVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class HotArticleServiceImpl implements HotArticleService {

    @Autowired
    private ApArticleMapper apArticleMapper;

    @Autowired
    private CacheService cacheService;

    @Override
    public void computeHotArticle() {
        // 1.查询五天内的文章
        LocalDateTime date = LocalDateTime.now().minusDays(5);
        List<ApArticle> articleByLast5days = apArticleMapper.last5Day(date);
        if (CollectionUtils.isEmpty(articleByLast5days)) {
            return;
        }

        // 2.计算分值
        List<HotArticleVo> hotArticleVos = computeScore(articleByLast5days);
        if (CollectionUtils.isEmpty(hotArticleVos)) {
            return;
        }

        // 3.分组并缓存
        groupAndCache(hotArticleVos);
    }

    private void groupAndCache(List<HotArticleVo> hotArticleVos) {
        // 3.按频道分组缓存
        List<List<HotArticleVo>> listGroupByChannel = CollectionUtil.groupByField(hotArticleVos, "channelId");
        if (CollectionUtil.isEmpty(listGroupByChannel)) {
            return;
        }

        for (List<HotArticleVo> list : listGroupByChannel) {
            if (CollectionUtil.isEmpty(list)) {
                continue;
            }

            Integer channelId = list.get(0).getChannelId();

            sortedAndCache(list, ArticleConstants.LOADTYPE_LOAD_MORE + channelId.toString());
        }

        // 4.推荐分一组
        sortedAndCache(hotArticleVos, ArticleConstants.HOT_ARTICLE_FIRST_PAGE+ArticleConstants.DEFAULT_TAG);
    }

    private void sortedAndCache(List<HotArticleVo> hotArticleVos, String key) {
        if (CollectionUtils.isEmpty(hotArticleVos) || StringUtils.isEmpty(key)) {
            return;
        }

        hotArticleVos = hotArticleVos.stream().sorted(Comparator.comparing(HotArticleVo::getScore).reversed()).collect(Collectors.toList());

        // 截取30条
        if (hotArticleVos.size() > 30) {
            hotArticleVos = hotArticleVos.subList(0, 30);
        }

        cacheService.set(key, JSON.toJSONString(hotArticleVos));
    }

    private List<HotArticleVo> computeScore(List<ApArticle> list) {
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }

        List<HotArticleVo> voList = new ArrayList<>();
        for (ApArticle apArticle : list) {
            if (apArticle == null) {
                continue;
            }

            // 计算得分
            HotArticleVo vo = compute(apArticle);
            if (vo == null) {
                continue;
            }

            voList.add(vo);
        }

        return voList;
    }

    private HotArticleVo compute(ApArticle article) {
        if (article == null) {
            return null;
        }

        Integer comment = article.getComment();
        Integer likes = article.getLikes();
        Integer views = article.getViews();
        Integer collection = article.getCollection();

        Integer score = 0;

        if (views != null) {
            score += views;
        }

        if (likes != null) {
            score += (ArticleConstants.HOT_ARTICLE_LIKE_WEIGHT * likes);
        }

        if (comment != null) {
            score += (ArticleConstants.HOT_ARTICLE_COMMENT_WEIGHT * comment);
        }

        if (collection != null) {
            score += (ArticleConstants.HOT_ARTICLE_COLLECTION_WEIGHT * collection);
        }

        HotArticleVo vo = new HotArticleVo();
        BeanUtils.copyProperties(article, vo);
        vo.setScore(score);
        return vo;
    }

}